package com.ruoyi.project.utils.alyunoss;

import cn.hutool.core.io.resource.InputStreamResource;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.ruoyi.framework.config.ALiOSSConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.UUID;

@Component
public class ALiOssUtil {

    @Autowired
    private OSSClient ossClient;
    @Autowired
    ALiOSSConfig ossConfig;


    private String uploadFile(String filename, InputStream inputStream) {

        ossClient.putObject(ossConfig.getBucketName(), filename, inputStream);
        // 返回文件的URL
        return ossClient.generatePresignedUrl(ossConfig.getBucketName(), filename, new Date(System.currentTimeMillis() + 3600 * 1000)).toString();
    }

    /**
     * 上传文件
     * @param file
     * @return
     * @throws IOException
     */
    public String uploadFile(MultipartFile file) throws IOException {

        // 获取文件的输入流
        InputStream inputStream = file.getInputStream();
        // 生成文件名
        String filename = UUID.randomUUID().toString() + file.getOriginalFilename();
        // 调用文件上传方法
        String fileUrl = uploadFile(filename, inputStream);
        return fileUrl;
    }


    /**
     * 以下是一个实现上传文件到OSS的方法，并不唯一
     */

    public String upload(MultipartFile file) throws IOException {
        //获取阿里云OSS参数
        String endpoint = ossConfig.getEndpoint();
        String accessKeyId = ossConfig.getAccessKeyId();
        String accessKeySecret = ossConfig.getAccessKeySecret();
        String bucketName = ossConfig.getBucketName();

        // 获取上传的文件的输入流
        InputStream inputStream = file.getInputStream();

        // 避免文件覆盖，需要使用UUID将文件重命名
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null) {
            throw new IllegalArgumentException("文件名为空");
        }
        int dotIndex = originalFilename.lastIndexOf(".");
        if (dotIndex == -1) {
            throw new IllegalArgumentException("文件名不包含扩展名");
        }
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(dotIndex);

        //上传文件到 OSS
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileName, inputStream);

        // 文件访问路径，可自行更改逻辑，重点是拼接url
        String[] endpointParts = endpoint.split("\\.");
        if (endpointParts.length != 3) {
            throw new IllegalArgumentException("无效的 endpoint 格式");
        }
        //url拼接
        String url = "https://" + bucketName + "." + endpointParts[0] + "." + endpointParts[1] +  "." + endpointParts[2] + "/" + fileName;
        //文件访问路径，若使用的yml，并配置了正确的endpoint，可使用以下方式
        //String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;


        // 关闭ossClient
        ossClient.shutdown();

        // 把上传到oss的路径返回
        return url;
    }


    /**
     * 下载文件
     * @param filename
     * @return
     * @throws IOException
     */
    public ResponseEntity<InputStreamResource> downloadFile(String filename) throws IOException {
        OSSObject ossObject = ossClient.getObject(ossConfig.getBucketName(), filename);
        // 调用文件下载方法
        InputStream inputStream = ossObject.getObjectContent();
        // 设置文件响应头
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition", "attachment; filename=" + filename);
        return ResponseEntity.ok()
                .headers(headers)
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(new InputStreamResource(inputStream));
    }
}
